home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / gcore / RCS / gcore.c,v < prev    next >
Encoding:
Text File  |  1991-10-25  |  14.7 KB  |  570 lines

  1. head     1.3;
  2. branch   ;
  3. access   ;
  4. symbols  ;
  5. locks    ; strict;
  6. comment  @ * @;
  7.  
  8.  
  9. 1.3
  10. date     91.10.25.10.28.35;  author jhh;  state Exp;
  11. branches ;
  12. next     1.2;
  13.  
  14. 1.2
  15. date     89.02.05.21.11.18;  author mendel;  state Exp;
  16. branches ;
  17. next     1.1;
  18.  
  19. 1.1
  20. date     89.02.05.20.50.52;  author mendel;  state Exp;
  21. branches ;
  22. next     ;
  23.  
  24.  
  25. desc
  26. @The gcore program.
  27. @
  28.  
  29.  
  30. 1.3
  31. log
  32. @now works on sun4's
  33. @
  34. text
  35. @/* 
  36.  * gcore.c --
  37.  *
  38.  *    This file contains a program that will produce a Unix
  39.  *    style core dump of a process.
  40.  *    See the man page for details on what it does.
  41.  *
  42.  * Copyright 1988 Regents of the University of California
  43.  * Permission to use, copy, modify, and distribute this
  44.  * software and its documentation for any purpose and without
  45.  * fee is hereby granted, provided that the above copyright
  46.  * notice appear in all copies.  The University of California
  47.  * makes no representations about the suitability of this
  48.  * software for any purpose.  It is provided "as is" without
  49.  * express or implied warranty.
  50.  */
  51.  
  52. #ifndef lint
  53. static char rcsid[] = "$Header: /a/newcmds/gcore/RCS/gcore.c,v 1.2 89/02/05 21:11:18 mendel Exp Locker: jhh $ SPRITE (Berkeley)";
  54. #endif not lint
  55.  
  56. #include <ctype.h>
  57. #include <option.h>
  58. #include <status.h>
  59. #include <stdio.h>
  60. #include <stdlib.h>
  61. #include <string.h>
  62. #include <signal.h>
  63. #include <sys/types.h>
  64. #include <sys/file.h>
  65. #include <kernel/proc.h>
  66. #include <a.out.h>
  67. #include <errno.h>
  68.  
  69. extern char *sys_errlist[];
  70.  
  71. #include "gcore.h"
  72.  
  73.  
  74. Boolean    debug = FALSE;            /* Output debugging info. */
  75. char    *outFilePrefix = "core";    /* Coredump output file. */
  76. #ifdef SAFETY
  77. Boolean    dumpRunningProcess = FALSE;    /* If true, an attempt is made to
  78.                      * dump process not in the debugger.
  79.                      */
  80. #else
  81. Boolean    dumpRunningProcess = TRUE;    /* If true, an attempt is made to
  82.                      * dump process not in the debugger.
  83.                      */
  84. #endif    
  85.  
  86. int    debugSignal = SIGTRAP;        /* Signal to bump process into the
  87.                      * debugger with.
  88.                      */
  89. Boolean killProcess = FALSE;        /* Kill process after dump. */
  90.  
  91. Option optionArray[] = {
  92.    {OPT_DOC,    (char *) NULL,    (char *) NULL,
  93.         "This program generates a core dump of a process.\n Synopsis:  \"gcore [options] pid [pid pid...]\"\nOptions are:"},
  94.    {OPT_STRING, "o", (char *) &outFilePrefix, "Prefix string for dump files."},
  95. #ifdef SAFETY
  96.    {OPT_TRUE,   "f", (char *) &dumpRunningProcess, 
  97.     "The dump the process evening if it is running."},
  98. #endif
  99.    {OPT_TRUE,   "k", (char *) &killProcess, "Kill processes after the dump."},  
  100.    {OPT_INT,    "s", (char *) &debugSignal, "Signal number to stop processes."},
  101.    {OPT_TRUE,    "d", (char *) &debug, "Output program debugging info."},
  102. };
  103.  
  104. /*
  105.  * Forward procedure declarations.
  106.  */
  107. static Boolean    DumpCore();
  108.  
  109.  
  110. /*
  111.  *----------------------------------------------------------------------
  112.  *
  113.  * main --
  114.  *
  115.  *    The main program for gcore.
  116.  *
  117.  * Results:
  118.  *    None.
  119.  *
  120.  * Side effects:
  121.  *    Writes output to sepcified file.
  122.  *
  123.  *----------------------------------------------------------------------
  124.  */
  125.  
  126. main(argc, argv)
  127.     int argc;        /* Number of command-line arguments. */
  128.     char **argv;    /* Values of command-line arguments. */
  129. {
  130.     int numCantDump;
  131.     int    i;
  132.  
  133.     argc = Opt_Parse(argc, argv, optionArray, Opt_Number(optionArray),0);
  134.     if (argc < 2) {
  135.     (void) fprintf(stderr,"Usage: %s [options] pid ...\n",PROGRAM_NAME);
  136.     exit(1);
  137.     } 
  138.     numCantDump = 0;
  139.     for (i = 1; i < argc; i++) {
  140.         int    pid;
  141.     char    *pidString;
  142.     char    *outFileName = malloc(strlen(outFilePrefix)+16);
  143.  
  144.     pidString = argv[i];
  145.         /*
  146.      * Convert the string pidString into an integer pid.
  147.      */
  148.     {
  149.         char    *endPtr;
  150.  
  151.         pid = strtoul(pidString, &endPtr, 16);
  152.         if (endPtr == pidString) {
  153.         (void) fprintf(stderr,"%s: Bad process id \"%s\"; ignoring\n", 
  154.             PROGRAM_NAME,  pidString);
  155.         numCantDump++;
  156.         continue;
  157.         }
  158.     
  159.     }
  160.     (void) sprintf(outFileName,"%s.%s",outFilePrefix,pidString);
  161.         if (DumpCore(pid, outFileName, pidString)) {
  162.         (void) printf("%s: %s dumped\n",PROGRAM_NAME,outFileName);
  163.     } else {
  164.         numCantDump++;
  165.     }
  166.     }
  167.     exit(numCantDump);
  168. }
  169.  
  170.  
  171.  
  172. /*
  173.  *----------------------------------------------------------------------
  174.  *
  175.  * GetProgramName --
  176.  *
  177.  *    Find the program name in the command string.
  178.  *
  179.  *    The routine takes a command string and returns the name of the 
  180.  *    program used in the command.  A command is assume to be a string
  181.  *    of the form:
  182.  *        commandPathname    arg1 arg2 arg3 ....
  183.  *    The program name is the file name of the exec file in the command.
  184.  *
  185.  * Results:
  186.  *    Nothing.
  187.  *
  188.  * Side effects:
  189.  *      None.
  190.  *
  191.  *----------------------------------------------------------------------
  192.  */
  193.  
  194. void 
  195. GetProgramName(argString,programName)
  196.     char    *argString;    /* Argument string of process. */
  197.     char    *programName;    /* Area to place program name. */
  198. {
  199.     register char    *endPtr, *startPtr;
  200.  
  201.     /*
  202.      * Strip any leading blanks.
  203.      */
  204.     while (*argString == ' ') {
  205.     argString++;
  206.     }
  207.     /*
  208.      * Locate the end of the program string. This is either the first blank
  209.      * or end of string.
  210.      */
  211.     endPtr = strchr(argString,' ');
  212.     if (endPtr == NULL) {
  213.     endPtr = argString + strlen(argString);
  214.     }
  215.     if (endPtr == argString) {
  216.     *programName = 0;
  217.     return;
  218.     }
  219.     /*
  220.      * From the end of the program string, find the beginning by working 
  221.      * backwards until the first '/' or beginning of string is found.
  222.      */
  223.     for (startPtr = endPtr - 1; startPtr > argString; startPtr--) {
  224.     if (*startPtr == '/') {
  225.         startPtr++;
  226.         break;
  227.     }
  228.     }
  229.     { 
  230.     int    len = endPtr - startPtr;
  231.     bcopy(startPtr, programName, len);
  232.     programName[len] = 0;
  233.     }
  234. }
  235.  
  236.  
  237.  
  238. /*
  239.  *----------------------------------------------------------------------
  240.  *
  241.  *  DumpCore --
  242.  *
  243.  *      Dump the core image of the specified process.
  244.  *
  245.  * Results:
  246.  *    True if dump succeeded, false otherwise.
  247.  *
  248.  * Side effects:
  249.  *      Core image is dumped to a file.
  250.  *
  251.  *----------------------------------------------------------------------
  252.  */
  253. static Boolean
  254. DumpCore(pid,coreFileName,pidString)
  255.     int     pid;            /* Process id to dump. */
  256.     char     *coreFileName;    /* Name of core file to create. */
  257.     char    *pidString;    /* String name of pid - use only for message. */
  258. {
  259.     char        *argString;    /* Argument string of process. */
  260.     char        *argStringProgram;
  261.     struct core        coreHeader;    /* Header written to coreFile. */
  262.     int            segSize[NUM_SEGMENTS];
  263.     FILE        *coreFile;    /* Core file. */
  264.     int            procState, procOrigState;
  265.     int            sigState;
  266.     Boolean        retVal = FALSE;
  267.     ProcExecHeader  header;
  268.    /*
  269.     * Find the status and argument string of the process. 
  270.     */
  271.  
  272.     argString = malloc(MAX_ARG_STRING_SIZE);
  273.     /*
  274.      * Find and record the original state of this process. 
  275.      */
  276.     sigState = debugSignal;
  277.     procOrigState = FindProcess(pid,argString,segSize,&sigState);
  278.  
  279.     if (procOrigState == NOT_FOUND_STATE) {
  280.      (void) fprintf(stderr, "%s: Process id %s not found.\n",
  281.             PROGRAM_NAME, pidString );
  282.     return (FALSE);
  283.     }
  284.     /*
  285.      * Insure that we can open the coreFile before signalling the process.
  286.      */
  287.      coreFile = fopen(coreFileName,"w");
  288.      if (coreFile == (FILE *) NULL) {
  289.      (void) fprintf(stderr,
  290.          "%s: Can't open %s: %s\n",PROGRAM_NAME,coreFileName,
  291.         sys_errlist[errno]);
  292.      return (FALSE);
  293.      }
  294.     /*
  295.      * If the process is not already in the DEBUG state, put it there.
  296.      */
  297.     if (procOrigState != DEBUG_STATE) {
  298.     /*
  299.      * Check to see if SAFETY is on.
  300.      */
  301.     if (!dumpRunningProcess) {
  302.         (void) fprintf(stderr,
  303.         "%s: Process id %s is running, must use -f to dump.\n",
  304.         PROGRAM_NAME, pidString);
  305.         (void) fclose(coreFile); (void) unlink(coreFileName);
  306.         return (FALSE);
  307.     }
  308.     /*
  309.      * See if the debugSignal is being held, ignored, or handled.
  310.      */
  311.     if (sigState != 0) {
  312.         char    *problem;
  313.  
  314.         if (sigState & SIG_IGNORING) {
  315.         problem = "ignoring";
  316.         } else if (sigState & SIG_HANDLING) {
  317.         problem = "handling";
  318.         } else if (sigState & SIG_HOLDING) {
  319.         problem = "holding";
  320.         } else {
  321.         problem = NULL;
  322.         }
  323.         if (problem) { 
  324.         (void) fprintf(stderr,
  325.             "%s: Process %s is %s signal %d; can't dump.\n",
  326.             PROGRAM_NAME, pidString, problem, debugSignal);
  327.         (void) fclose(coreFile); (void) unlink(coreFileName);
  328.         return (FALSE);
  329.         }
  330.     }
  331.     /*
  332.      * Try bumping the process into the debugger. This will fail if the
  333.      * user can't signal the process.
  334.      */
  335.     if(kill(pid,debugSignal) < 0) {
  336.         (void) fprintf(stderr,
  337.             "%s: Can't signal process %s with signal %d: %s\n",
  338.             PROGRAM_NAME, pidString, debugSignal,sys_errlist[errno]);
  339.         (void) fclose(coreFile); (void) unlink(coreFileName);
  340.         return (FALSE);
  341.      } 
  342.      (void) sleep(1);
  343.      procState = FindProcess(pid,argString,segSize,(int *) 0);
  344.      /* 
  345.       * If process is still not in the debug state, trying giving it a
  346.       * SIGCONT.  This appears to be necessary to get suspended process
  347.       * into the debug state.
  348.       */
  349.      if (procState == SUSPEND_STATE) {
  350.         (void) kill(pid,SIGCONT);
  351.             (void) sleep(1);
  352.         procState = FindProcess(pid,argString,segSize,(int *) 0);
  353.      }
  354.      if (procState != DEBUG_STATE) {
  355.          if (procState == NOT_FOUND_STATE) {
  356.         (void) fprintf(stderr,
  357.             "%s: Process id %s disappeared after signal %d, sorry.\n",
  358.             PROGRAM_NAME, pidString,debugSignal);
  359.         } else {
  360.         (void) fprintf(stderr,
  361.             "%s: Process %s wont stop for signal %d.\n",
  362.             PROGRAM_NAME, pidString, debugSignal);
  363.         }
  364.         (void) fclose(coreFile); (void) unlink(coreFileName);
  365.         return (FALSE);
  366.     }
  367.     }
  368.     /*
  369.      * Attach the process using the debugger interface. 
  370.      */
  371.     if (!AttachProcess(pid)) {
  372.     (void) fprintf(stderr,
  373.            "%s: Can't attach process %s\n",PROGRAM_NAME, pidString);
  374.     (void) fclose(coreFile); (void) unlink(coreFileName);
  375.     return(FALSE);
  376.     }
  377.  
  378.     /* Find the program name from the argument string. */
  379.  
  380.     argStringProgram = malloc(strlen(argString)+1);
  381.     GetProgramName(argString,argStringProgram);
  382.  
  383.     /*
  384.      * Fill in the core file header with our best guess.
  385.      */
  386.      coreHeader.c_magic = CORE_MAGIC;
  387.      coreHeader.c_len = sizeof(struct core);
  388.      if (!ReadStopInfoFromProcess(pid,&coreHeader.c_signo,&coreHeader.c_regs)) {
  389.      (void) fprintf(stderr,
  390.             "%s: Can't read regs of process %s\n",PROGRAM_NAME,
  391.             pidString);
  392.      (void) fclose(coreFile); 
  393.      goto errout;
  394.      }
  395.      /*
  396.       * Fill in the exec file header with our best guesses.
  397.       */
  398.      bzero((char *)&coreHeader.c_aouthdr,sizeof(coreHeader.c_aouthdr));
  399.      coreHeader.c_aouthdr.a_magic = ZMAGIC;
  400.      coreHeader.c_aouthdr.a_text = segSize[TEXT_SEG];
  401.      coreHeader.c_aouthdr.a_data = segSize[DATA_SEG];
  402.  
  403.      coreHeader.c_tsize = coreHeader.c_aouthdr.a_text;
  404.      (void) strncpy(coreHeader.c_cmdname,argStringProgram,CORE_NAMELEN);
  405.  
  406.      /*
  407.       * Write empty coreHeader to be filled in later. This reserve space
  408.       * in the output file for the header.
  409.       */
  410.      if (fwrite((char *)&coreHeader,sizeof(coreHeader),1,coreFile) != 1) {
  411.      (void) fprintf(stderr,"%s: Can't write file %s: %s\n",PROGRAM_NAME,
  412.         coreFileName,sys_errlist[errno]);
  413.      (void) fclose(coreFile);
  414.      goto errout;
  415.      }
  416.  
  417.     /*
  418.      * Follow the coreHeader with the data segment
  419.      */
  420.      {
  421.     bcopy((char *)&coreHeader.c_aouthdr,(char *)&header, sizeof(header));
  422.         coreHeader.c_dsize = XferSegmentFromProcess(pid,
  423.         (unsigned int) PROC_DATA_LOAD_ADDR(header),coreFile);
  424.      }
  425.      if (coreHeader.c_dsize <= 0) {
  426.      (void) fprintf(stderr,"%s: Can't read data segment.\n",PROGRAM_NAME);
  427.      (void) fclose(coreFile);
  428.      goto errout;
  429.      }
  430.  
  431.     /*
  432.      * And then the stack segment starting with at the stack pointer.
  433.      */
  434.      coreHeader.c_ssize = XferSegmentFromProcess(pid,
  435.                    (unsigned int) coreHeader.c_regs.r_sp, coreFile);
  436.      if (coreHeader.c_ssize <= 0) {
  437.      (void) fprintf(stderr,"%s: Can't read stack segment.\n",PROGRAM_NAME);
  438.      (void) fclose(coreFile);
  439.      goto errout;
  440.      }
  441.      /*
  442.       * Now rewrite the coreFile header with the new data and stack segment
  443.       * sizes.
  444.       */
  445.      if (fseek(coreFile,0,0) < 0) {
  446.      (void) fprintf(stderr,
  447.         "%s: Can't rewrite file %s header: %s\n",PROGRAM_NAME,
  448.         coreFileName,sys_errlist[errno]);
  449.      }
  450.      if (fwrite((char *)&coreHeader,sizeof(coreHeader),1,coreFile) != 1) {
  451.      (void) fprintf(stderr,"%s: Can't write %s : %s\n",PROGRAM_NAME,
  452.         coreFileName,sys_errlist[errno]);
  453.      (void) fclose(coreFile);
  454.      goto errout;
  455.      }
  456.      if (fclose(coreFile) != 0)  {
  457.      (void) fprintf(stderr,"%s: Error closing %s : %s\n",PROGRAM_NAME,
  458.         coreFileName,sys_errlist[errno]);
  459.      }
  460.      retVal = TRUE;
  461.      /* 
  462.       * Did the user want the process dead?
  463.       */
  464.      if (killProcess && (kill(pid,SIGKILL) < 0)) {
  465.      (void) fprintf(stderr,
  466.             "%s: Can't kill process %s: %s\n",
  467.             PROGRAM_NAME, pidString, sys_errlist[errno]);
  468.      }
  469.  errout:
  470.      /*
  471.       * Detach the debugger from the process. If the process was in
  472.       * the suspend state the detach will start it running again. 
  473.       * The current thinking is that this is not good so we leave
  474.       * suspended processes in the debugger.
  475.       */
  476.      if (killProcess || ! ( (procOrigState == SUSPEND_STATE) ||
  477.                 (procOrigState == DEBUG_STATE))) {
  478.      static char *procStateNames[] = STATE_NAMES;
  479.      (void) DetachProcess(pid);
  480.      (void) sleep(1);
  481.      procState = FindProcess(pid,argString,(int *) 0,(int *) 0);
  482.      /*
  483.       * If we didn't want it dead and it died?
  484.       */
  485.      if (!killProcess && (procState == NOT_FOUND_STATE)) {
  486.         (void) fprintf(stderr,
  487.         "%s: Warning: Process %s disappeared after dump, sorry.\n",
  488.         PROGRAM_NAME, pidString);
  489.      } else if (killProcess && (procState != NOT_FOUND_STATE)) {
  490. #ifdef notdef
  491.     /*
  492.      * This doesn't appear to work.
  493.      */
  494.         (void) fprintf(stderr,
  495.         "%s: Warning: Process %s didn't die.\n",PROGRAM_NAME, 
  496.          pidString);
  497. #endif
  498.      } else if (procState != procOrigState) {
  499.          (void) fprintf(stderr,
  500.         "%s: Warning: Process %s new state is %s was %s\n",
  501.         PROGRAM_NAME, pidString,procStateNames[procState],
  502.         procStateNames[procOrigState]);
  503.      } 
  504.      }
  505.      if (!retVal) {
  506.      (void) unlink(coreFileName);
  507.      (void) fclose(coreFile);
  508.      }
  509.      return (retVal);
  510. }
  511.  
  512. @
  513.  
  514.  
  515. 1.2
  516. log
  517. @Cleanup for lint.
  518. @
  519. text
  520. @d19 1
  521. a19 1
  522. static char rcsid[] = "$Header: /a/newcmds/gcore/RCS/gcore.c,v 1.1 89/02/05 20:50:52 mendel Exp Locker: mendel $ SPRITE (Berkeley)";
  523. a31 1
  524. #include <kernel/procAOUT.h>
  525. d108 1
  526. a108 1
  527.     char    *outFileName = alloca(strlen(outFilePrefix)+16);
  528. d233 1
  529. d238 1
  530. a238 1
  531.     argString = alloca(MAX_ARG_STRING_SIZE);
  532. a333 1
  533.  
  534. d346 1
  535. a346 1
  536.     argStringProgram = alloca(strlen(argString)+1);
  537. a386 1
  538.     Proc_AOUT header;
  539. @
  540.  
  541.  
  542. 1.1
  543. log
  544. @Initial revision
  545. @
  546. text
  547. @d19 1
  548. a19 1
  549. static char rcsid[] = "$Header: /a/newcmds/ps/RCS/ps.c,v 1.13 88/12/22 11:04:48 douglis Exp $ SPRITE (Berkeley)";
  550. d271 1
  551. a271 1
  552.         fclose(coreFile); unlink(coreFileName);
  553. d293 1
  554. a293 1
  555.         fclose(coreFile); unlink(coreFileName);
  556. d305 1
  557. a305 1
  558.         fclose(coreFile); unlink(coreFileName);
  559. d330 1
  560. a330 1
  561.         fclose(coreFile); unlink(coreFileName);
  562. d341 1
  563. a341 1
  564.     fclose(coreFile); unlink(coreFileName);
  565. d474 2
  566. a475 2
  567.      unlink(coreFileName);
  568.      fclose(coreFile);
  569. @
  570.